import 'package:flutter/widgets.dart';
import 'package:imperius_insights/portal/env/environments.dart';
import 'package:imperius_insights/portal/state/mobx/store.dart';
import 'package:mobx/mobx.dart';

import 'store.dart';
import 'typings.dart';

part 'view_model.g.dart';

class ViewModel = _ViewModel with _$ViewModel;

abstract class _ViewModel with Store, StoreWithLifecycle {
  DiagnosticStore _diagnosticStore;
  @observable
  ObservableList<Investigation> investigations;
  bool wasNotInHouseNetwork;
  bool hasApiInternalIssue;

  ScrollController _scrollController;

  ScrollController get scrollController => _scrollController;

  _ViewModel() {
    _diagnosticStore = DiagnosticStore();
    investigations = ObservableList<Investigation>();
  }

  @override
  onContextAttached(BuildContext context) {
    super.onContextAttached(context);
    hasApiInternalIssue = false;
    wasNotInHouseNetwork = false;
    _diagnosticStore.launchDiagnostic(
        onCheckingTarget: onCheckingTarget,
        onApiHealthChecked: onApiHealthChecked,
        onRequestMeasured: onRequestMeasured,
        onConnectivityInfoResolved: onConnectivityInfoResolved,
        onNetworkInfoResolved: onNetworkInfoResolved);
  }

  setupListController(ScrollController scrollController) {
    this._scrollController = scrollController;
  }

  @action
  void onCheckingTarget(EnumCheckingTarget checkingTarget) {
    if (investigations.length > 0) investigations.removeLast();
    if (checkingTarget == EnumCheckingTarget.Completed) {
      investigations
          .add(Investigation('诊断结束', status: EnumInvestigateStatus.none));
      if (wasNotInHouseNetwork) {
        investigations
            .add(Investigation('关键问题：无法访问到Qunar内部网络，尝试使用VPN或更换到chanpin-5G网络', status: EnumInvestigateStatus.suggest));
      }
      if (hasApiInternalIssue) {
        investigations
            .add(Investigation('API服务出现故障，请联系meng.jiang获取支持', status: EnumInvestigateStatus.suggest));
      }
      scrollToEnd();
      return;
    }
    if (checkingTarget == EnumCheckingTarget.NetworkInfo) {
      investigations.add(
          Investigation('正在检查网络接入点', status: EnumInvestigateStatus.underway));
      return;
    }
    if (checkingTarget == EnumCheckingTarget.ConnectivityInfo) {
      investigations.add(
          Investigation('正在收集网络连接信息', status: EnumInvestigateStatus.underway));
      return;
    }
    if (checkingTarget == EnumCheckingTarget.Measurements) {
      investigations.add(
          Investigation('正在检测网络连通性能', status: EnumInvestigateStatus.underway));
      return;
    }
    if (checkingTarget == EnumCheckingTarget.HealthCheck) {
      investigations.add(Investigation('正在检测API服务',
          status: EnumInvestigateStatus.underway));
      return;
    }
  }

  @action
  dynamic onNetworkInfoResolved(NetworkInfo networkInfo) {
    if (networkInfo != null) {
      investigations.insert(
          investigations.length - 1,
          Investigation('网络类型：${networkInfo.networkType}',
              status: EnumInvestigateStatus.pass));
      return true;
    }
    investigations.insert(
        investigations.length - 1,
        Investigation('该设备未启用网络，请设置开启移动或WIFI',
            status: EnumInvestigateStatus.error));
    return false;
  }

  @action
  dynamic onConnectivityInfoResolved(ConnectivityInfo connectivityInfo) {
    var extraNetInfo = '';
    if (connectivityInfo.networkInfo is WifiNetworkInfo) {
      WifiNetworkInfo wni = connectivityInfo.networkInfo;
      if (wni.name != null) extraNetInfo += '\nWIFI名称 = ${wni.name}';
      if (wni.innerIp != null) extraNetInfo += '\n内网IP = ${wni.innerIp}';
      if (wni.ssid != null) extraNetInfo += '\nSSID = ${wni.ssid}';
      if (wni.mac != null) extraNetInfo += '\nMAC地址 = ${wni.mac}';
    }
    if (!connectivityInfo.available && !isWebRuntime) {
      investigations.insert(
          investigations.length - 1,
          Investigation('无法访问到Internet，请尝试更换网络接入方式$extraNetInfo',
              status: EnumInvestigateStatus.error));
      return false;
    }
    investigations.insert(
        investigations.length - 1,
        Investigation(
            '可以访问Internet\n出站IP = ${connectivityInfo
                .overtIp}\nLocalDNS = ${connectivityInfo
                .localDns}$extraNetInfo',
            status: EnumInvestigateStatus.pass));
    return true;
  }

  @action
  onRequestMeasured(MeasurementRequest request, MeasurementResult result) {
    String extra = '';
    if (result.summary.P90 >= 0) {
      extra += '\n延迟：P90=${result.summary.P90}ms';
    }
    if (result.summary.P50 >= 0) {
      extra += ' P50=${result.summary.P50}ms';
    }
    if (result.summary.avg >= 0) {
      extra += ' avg=${result.summary.avg}ms';
    }
    if ((request.uri.contains('100.81') || request.uri.contains('qunar.it')) && result.summary.availableRatio == 0) {
      wasNotInHouseNetwork = true;
    }
    investigations.insert(
        investigations.length - 1,
        Investigation(
            '访问${request.name}\n成功率：${result.summary.availableRatio *
                100}%$extra',
            status: result.summary.availableRatio > 0.8
                ? EnumInvestigateStatus.pass
                : EnumInvestigateStatus.error));
    scrollToEnd();
  }

  scrollToEnd() {
    Future.delayed(Duration(milliseconds: 100), () {
      if (!scrollController.hasClients) {
        return;
      }
      scrollController.animateTo(scrollController.position.maxScrollExtent,
          duration: Duration(seconds: 1), curve: Curves.decelerate);
    });
  }

  @action
  onApiHealthChecked(HealthCheckRequest request, HealthCheckResult result) {
    String errorIssues = '';
    errorIssues = result.errorTypes.map((type) {
      if (type == EnumErrorType.UnableConnect) return '· 无法连接到此服务';
      if (type == EnumErrorType.ServiceError) {
        hasApiInternalIssue = true;
        return '· 服务内部错误';
      }
      if (type == EnumErrorType.Instability) return '· API接口不稳定';
      return '';
    }).join('\n');

    if (errorIssues.length > 0) {
      errorIssues = '\n存在以下问题：\n$errorIssues';
    }
    String extra = '';
    if (result.summary.P90 >= 0) {
      extra += '\n延迟：P90=${result.summary.P90}ms';
    }
    if (result.summary.P50 >= 0) {
      extra += ' P50=${result.summary.P50}ms';
    }
    if (result.summary.avg >= 0) {
      extra += ' avg=${result.summary.avg}ms';
    }
    investigations.insert(
        investigations.length - 1,
        Investigation(
            '访问API ${request.name}\n成功率：${result.summary.availableRatio *
                100}%(${result.summary.successTimes}/${result.summary
                .sampleTimes})$errorIssues$extra',
            status: mapRatio2Status(result.summary.availableRatio)));
    scrollToEnd();
  }

  EnumInvestigateStatus mapRatio2Status(double availableRatio) {
    if (availableRatio > 0.95) {
      return EnumInvestigateStatus.pass;
    }
    if (availableRatio > 0.8) {
      return EnumInvestigateStatus.warn;
    }
    return EnumInvestigateStatus.error;
  }
}

enum EnumInvestigateStatus { underway, pending, pass, warn, error, none, suggest }

class Investigation {
  EnumInvestigateStatus status;
  String text;

  Investigation(this.text, {this.status: EnumInvestigateStatus.underway});
}
